﻿/*
 *  ChgDoc CMS - GNU General Public License, version 3 (GPL-3.0)
 *  Copyright (C)  2012. Ian Quigley
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ChgDoc.Entity;
using RazorEngine;
using RazorEngine.Templating;
using System.Web;
using System.Web.Caching;
using ChgDoc.Extension;
using StackExchange.Profiling;


namespace ChgDoc.Render
{
	public class TemplateRenderParameters : ResponseRenderParameters<TemplateRenderParameters>
	{
		public long TemplateId { get; set; }
        public long CacheDurationSeconds { get; set; }
	}

	public class UtilModel
	{
		public Config Config;
		public Toolbox Tools;
        public Visitor Visitor;
	}

    public class TemplateRender : ResponseRender
    {
        private readonly TemplateRenderParameters _parameters;

        public TemplateRender( string constructionString )
        {
            _parameters = TemplateRenderParameters.Deserialize( constructionString );
        }

        public override void Render( HttpContext context )
        {
            TryFromCache(context, context.Request.RawUrl.ToLower(), _parameters.CacheDurationSeconds, () =>
                {
                    var template = Template.Read(_parameters.TemplateId);
                    if (template == null)
                        return string.Empty;

                    switch (template.RenderEngineCode.ToLower())
                    {
                        case "razor":
                            return RenderRazor(template, new UtilModel() { Config = Config.Current, Tools = new Toolbox(template), Visitor = Visitor.Current });

                        case "plain":
                            return template.Body;

                        default:
                            return string.Empty;
                    }
                });
        }

        public static string RenderRazor<T>( Template template, T model )
        {
            string render;
            try
            {
                using (MiniProfiler.Current.Step( "Render Template:" + template.Name ))
                    render = RazorEngine.Razor.Parse( template.Body, model );
            }
            catch (TemplateCompilationException ex)
            {
                Config.Log.Error("** Render Exception", ex);

                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("<html><h3>Compilation errors  {0}</h3>", ex.Message);
                foreach (var error in ex.Errors)
                {
                    sb.AppendLine("Compile Error Num: " + error.ErrorNumber + "<br/>");
                    sb.AppendLine("Error Text:<pre>" + error.ErrorText + "</pre><br/>");
                }
                render = sb.ToString();                
            }
            catch (Exception ex)
            {
                render = ex.Message;
                Config.Log.Error("** Render Exception", ex);
            }

            return render;
        }

        public static void TryFromCache( HttpContext context, string key, long cacheDurationSeconds, Func<string> createHtml )
        {
            if (string.IsNullOrWhiteSpace(key))
                key = "jcpjwpcu-230ud03ud23dmd39";

            string html = (string)context.Cache.Get( key );
            
            if (html == null)
            {
                html = createHtml();
                context.Cache.Add(key, html.Replace("</body>", "<!-- cached -->\n</body>"), null, Cache.NoAbsoluteExpiration, TimeSpanHelper.FromLongSeconds(cacheDurationSeconds), System.Web.Caching.CacheItemPriority.Normal, null);
            }

            context.Response.Write( html );
        }        
    }
	
}
